package com.ibeeking.found.open.b.rest.service.impl;


import com.ibeeking.found.common.constants.WxCpServiceTypeConstant;
import com.ibeeking.found.common.entity.open.*;
import com.ibeeking.found.common.enums.OpenApiConfigEnum;
import com.ibeeking.found.common.enums.WxCpAppTypeEnum;
import com.ibeeking.found.common.response.ResponseCodeEnum;
import com.ibeeking.found.common.utils.DataUtils;
import com.ibeeking.found.common.utils.UrlUtils;
import com.ibeeking.found.common.utils.UserUtils;
import com.ibeeking.gmc.global.api.feign.GlobalOpenFeignClient;
import com.ibeeking.found.open.api.common.param.OpenAuthCancelParam;
import com.ibeeking.found.open.api.common.param.OpenAuthParam;
import com.ibeeking.found.open.api.feign.CopFeignClient;
import com.ibeeking.found.open.api.feign.OpenFileFeignClient;
import com.ibeeking.found.open.api.feign.GlobalOpenAuthFeignClient;
import com.ibeeking.found.open.b.rest.config.prop.RedisProperties;
import com.ibeeking.found.open.b.rest.service.IOpenService;
import com.ibeeking.found.open.b.rest.service.IWxCpDkEventService;
import com.ibeeking.found.open.service.common.constants.RedisKeyConstant;
import com.ibeeking.found.open.service.common.dto.WxCpDkQrCodeDTO;
import com.ibeeking.found.open.service.common.vo.OpenAuthVO;
import com.ibeeking.found.open.service.common.vo.UrlVO;
import com.ibeeking.found.open.service.config.OpenAuthCallBackConfig;
import com.ibeeking.nematos.exception.BusinessException;
import com.ibeeking.nematos.file.oss.dto.OssPolicyDto;
import com.ibeeking.nematos.log.utils.LogUtils;
import com.ibeeking.nematos.qrcode.Codectx;
import com.ibeeking.nematos.qrcode.qrcode.QrcodeConfig;
import com.ibeeking.nematos.qrcode.qrcode.QreyesFormat;
import com.ibeeking.nematos.qrcode.qrcode.SimpleQrcodeGenerator;
import com.ibeeking.nematos.redis.utils.RedisUtils;
import com.ibeeking.nematos.utils.bean.BeanUtil;
import com.ibeeking.nematos.utils.data.Collections3;
import com.ibeeking.nematos.utils.data.StringUtils;
import com.ibeeking.nematos.utils.file.FileUtils;
import com.ibeeking.nematos.utils.json.JsonUtils;
import com.ibeeking.nematos.utils.result.ResponseResult;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.bean.WxAccessToken;
import me.chanjar.weixin.common.enums.WxType;
import me.chanjar.weixin.common.error.WxError;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.error.WxRuntimeException;
import me.chanjar.weixin.common.session.WxSessionManager;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.bean.WxCpProviderToken;
import me.chanjar.weixin.cp.bean.WxCpTpPermanentCodeInfo;
import me.chanjar.weixin.cp.bean.WxTpCustomizedAuthUrl;
import me.chanjar.weixin.cp.bean.message.*;
import me.chanjar.weixin.cp.config.WxCpTpConfigStorage;
import me.chanjar.weixin.cp.config.impl.WxCpTpDefaultConfigImpl;
import me.chanjar.weixin.cp.constant.WxCpApiPathConsts;
import me.chanjar.weixin.cp.constant.WxCpTpConsts;
import me.chanjar.weixin.cp.message.WxCpMessageHandler;
import me.chanjar.weixin.cp.message.WxCpMessageRouter;
import me.chanjar.weixin.cp.tp.service.WxCpTpService;
import me.chanjar.weixin.cp.tp.service.impl.WxCpTpServiceImpl;
import me.chanjar.weixin.cp.util.crypto.WxCpTpCryptUtil;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.entity.ContentType;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.CloseableHttpClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;


/**
 * @ClassName WxCpTpEventServiceImpl
 * @Description
 * @Author ibeeking
 * @Date 2021-06-18 12:21
 **/
@Service("wxCpDkEventServiceImpl")
@EnableConfigurationProperties({RedisProperties.class})
public class WxCpDkEventServiceImpl implements IWxCpDkEventService {
    private static final Logger log = LoggerFactory.getLogger(WxCpDkEventServiceImpl.class);

    private static final Integer EXPIRE_TIME = 7000; // 100分钟

    private static final Map<String, WxCpMessageRouter> wxCpMessageRouterMap = new Hashtable();

    @Resource
    private RedisUtils redisUtils;

    @Autowired
    private RedisProperties redisProperties;

    @Resource
    private OpenFileFeignClient openFileFeignClient;

    @Resource
    private CopFeignClient copFeignClient;

    @Resource
    private IOpenService openServiceImpl;

    @Resource
    private GlobalOpenAuthFeignClient globalOpenAuthFeignClient;

    @Resource
    private GlobalOpenFeignClient globalOpenFeignClient;

    @Resource
    private OpenAuthCallBackConfig openAuthCallBackConfig;

    @Override
    public String authWxCpDkTicket(HttpServletRequest request, HttpServletResponse response, String signature, String timestamp, String nonce, String echostr) {
        try {
            OpenConfigDTO wxOpenConfigDTO = queryWxOpenConfigByType(OpenApiConfigEnum.OPEN_CONFIG_TYPE_WECHAT_CP.getCode(), WxCpAppTypeEnum.WECHAT_CP_APP_TYPE_DK.getCode());
            if (null == wxOpenConfigDTO) {
                throw new BusinessException("无法获取开发平台参数信息");
            }
            WxCpTpService wxCpDkService = openServiceImpl.getDefaultWxCpDkService();
            if (wxCpDkService == null)  throw new BusinessException("获取企微服务失败!");
            WxCpTpConfigStorage wxCpDkConfigStorage = wxCpDkService.getWxCpTpConfigStorage();

            WxCpTpCryptUtil cryptUtil = new WxCpTpCryptUtil(wxCpDkConfigStorage);
            String encryptedXml = IOUtils.toString(request.getInputStream(), StandardCharsets.UTF_8);

            String inMessage = cryptUtil.decryptXml(signature, timestamp, nonce, encryptedXml);
            if(inMessage == null) return "success";

            LogUtils.info("auth:消息解密后内容为：\n{} ", JsonUtils.toJsonStr(inMessage));

            WxCpTpXmlMessage wxCpTpXmlMessage = WxCpTpXmlMessage.fromXml(inMessage);
            Map<String, Object> jsonObject = wxCpTpXmlMessage.getAllFieldsMap();
            String out = null;
            if(WxCpTpConsts.InfoType.SUITE_TICKET.equals(wxCpTpXmlMessage.getInfoType())) {
                String suitId = wxCpTpXmlMessage.getSuiteId();
                String suiteTicket = wxCpTpXmlMessage.getSuiteTicket();
                Integer timeStamp = Integer.getInteger(wxCpTpXmlMessage.getTimeStamp());
                LogUtils.info("\nSUITE_TICKET：\n{} ", JsonUtils.toJsonStr(wxCpTpXmlMessage));

                wxCpDkConfigStorage.updateSuiteTicket(suiteTicket, 20*60);
                redisUtils.set(RedisKeyConstant.WX_CP_DK_SUITE_TICKET + suitId,suiteTicket,20*60);
                checkAndUpdateSuiteToken(wxCpDkService, suitId, signature, timestamp, nonce);
                checkAndUpdateWxCpDkAuthorizeAccessToken(wxCpDkService, suitId, signature, timestamp, nonce);
            } else if(WxCpTpConsts.InfoType.CREATE_AUTH.equals(wxCpTpXmlMessage.getInfoType())){
                this.saveAndUpdateWxCpDk(wxCpDkService, wxOpenConfigDTO, wxCpTpXmlMessage);
            } else if(WxCpTpConsts.InfoType.CHANGE_AUTH.equals(wxCpTpXmlMessage.getInfoType())){
                this.saveAndUpdateWxCpDk(wxCpDkService, wxOpenConfigDTO, wxCpTpXmlMessage);
            } else if(WxCpTpConsts.InfoType.CANCEL_AUTH.equals(wxCpTpXmlMessage.getInfoType())){
                String suiteAppId = wxCpTpXmlMessage.getSuiteId();
                String authCorpId = wxCpTpXmlMessage.getAuthCorpId();
                LogUtils.info("\nCANCEL_AUTH：\n{} ", JsonUtils.toJsonStr(wxCpTpXmlMessage));
                OpenAuthCancelParam param = new OpenAuthCancelParam();
                param.setOpenAppId(wxOpenConfigDTO.getOpenAppId());
                param.setAppId(authCorpId);
                param.setComponentAppId(suiteAppId);
                globalOpenAuthFeignClient.cancelAuth(param);

            }  else if(WxCpTpConsts.InfoType.CHANGE_CONTACT.equals(wxCpTpXmlMessage.getInfoType())){
                if (StringUtils.isEmpty(wxCpTpXmlMessage.getChangeType())){
                    throw new Exception("该类型通讯录变更不存在");
                }
                if("create_user".equalsIgnoreCase(wxCpTpXmlMessage.getChangeType())){
                    LogUtils.info("\ncreate_user：\n{} ", JsonUtils.toJsonStr(wxCpTpXmlMessage));
                }else if("update_user".equalsIgnoreCase(wxCpTpXmlMessage.getChangeType())){

                    LogUtils.info("\nupdate_user：\n{} ", JsonUtils.toJsonStr(wxCpTpXmlMessage));
                }else if("delete_user".equalsIgnoreCase(wxCpTpXmlMessage.getChangeType())){

                    LogUtils.info("\ndelete_user：\n{} ", JsonUtils.toJsonStr(wxCpTpXmlMessage));
                }else if("create_party".equalsIgnoreCase(wxCpTpXmlMessage.getChangeType())){

                    LogUtils.info("\ncreate_party：\n{} ", JsonUtils.toJsonStr(wxCpTpXmlMessage));
                }else if("update_party".equalsIgnoreCase(wxCpTpXmlMessage.getChangeType())){

                    LogUtils.info("\nupdate_party：\n{} ", JsonUtils.toJsonStr(wxCpTpXmlMessage));
                }else if("delete_party".equalsIgnoreCase(wxCpTpXmlMessage.getChangeType())){

                    LogUtils.info("\ndelete_party：\n{} ", JsonUtils.toJsonStr(wxCpTpXmlMessage));
                }else if("update_tag".equalsIgnoreCase(wxCpTpXmlMessage.getChangeType())){

                    LogUtils.info("\nupdate_tag：\n{} ", JsonUtils.toJsonStr(wxCpTpXmlMessage));
                }
            }else if(WxCpTpConsts.InfoType.CHANGE_EXTERNAL_CONTACT.equals(wxCpTpXmlMessage.getInfoType())){
                if (StringUtils.isEmpty(wxCpTpXmlMessage.getChangeType())){
                    throw new Exception("该类型外部联系人通讯录变更不存在");
                }
                if("add_external_contact".equalsIgnoreCase(wxCpTpXmlMessage.getChangeType())){

                    LogUtils.info("\nadd_external_contact：\n{} ", JsonUtils.toJsonStr(wxCpTpXmlMessage));
                }else if("edit_external_contact".equalsIgnoreCase(wxCpTpXmlMessage.getChangeType())){

                    LogUtils.info("\nedit_external_contact：\n{} ", JsonUtils.toJsonStr(wxCpTpXmlMessage));
                }else if("del_external_contact".equalsIgnoreCase(wxCpTpXmlMessage.getChangeType())){

                    LogUtils.info("\ndel_external_contact：\n{} ", JsonUtils.toJsonStr(wxCpTpXmlMessage));
                }
            }

            return "success";
        }catch(Exception ex){
            return "success";
        }

    }

    private void saveAndUpdateWxCpDk(WxCpTpService wxCpTpService, OpenConfigDTO wxOpenConfigDTO, WxCpTpXmlMessage wxCpTpXmlMessage) throws WxErrorException{
        WxCpTpConfigStorage wxCpTpConfigStorage = wxCpTpService.getWxCpTpConfigStorage();
        String suiteId = wxCpTpXmlMessage.getSuiteId();
        String authCode =  wxCpTpXmlMessage.getAuthCode();
        String timeStamp = wxCpTpXmlMessage.getTimeStamp();
        String tenantId = wxCpTpXmlMessage.getState();

        LogUtils.info("\nCREATE_AUTH：\n{} ", JsonUtils.toJsonStr(wxCpTpXmlMessage));

        Long openId = wxOpenConfigDTO.getId();
        String openAppId  = wxOpenConfigDTO.getOpenAppId();

        OpenAuthParam param = new OpenAuthParam();
        OpenAuthOfExtend openAuthOfExtend = new OpenAuthOfExtend();

        OssPolicyDto  ossPolicyDto = getOssFilePolicy();
        if(StringUtils.isNotEmpty(tenantId)){
            param.setTenantId(Long.valueOf(tenantId));
        }
        param.setOpenId(openId);
        param.setOpenAppId(openAppId);
        param.setConfigType(wxOpenConfigDTO.getType());
        param.setConfigSubType(wxOpenConfigDTO.getSubType());
        param.setComponentAppId(suiteId);
        param.setComponentAppSecret(wxOpenConfigDTO.getComponentSecret());
        param.setAppToken(wxOpenConfigDTO.getComponentMsgToken());
        param.setAppAesKey(wxOpenConfigDTO.getComponentMsgAesKey());
        param.setAppType(WxCpAppTypeEnum.WECHAT_CP_APP_TYPE_DK.getCode());

        String suiteTicket = wxCpTpConfigStorage.getSuiteTicket();
        if(StringUtils.isEmpty(suiteTicket)){
            Object suiteTicketObj = redisUtils.get(RedisKeyConstant.WX_CP_DK_SUITE_TICKET + suiteId);
            if(ObjectUtils.isNotEmpty(suiteTicketObj)) {
                suiteTicket = suiteTicketObj.toString();
                wxCpTpConfigStorage.updateSuiteTicket(suiteTicket, 1200);
            }
        }
        OpenAuthOfWxCpDk openAuthOfWxCpDk = new OpenAuthOfWxCpDk();
        openAuthOfWxCpDk.setSuiteTicket(suiteTicket);

        WxAccessToken wxAccessToken = wxCpTpService.getSuiteAccessTokenEntity(true);
        if(ObjectUtils.isNotEmpty(wxAccessToken)) {
            wxCpTpConfigStorage.updateSuiteAccessToken(wxAccessToken);
            openAuthOfWxCpDk.setSuiteAccessToken(wxAccessToken.getAccessToken());
            openAuthOfWxCpDk.setSuiteAccessExpirein(System.currentTimeMillis() + wxAccessToken.getExpiresIn() * 1000);
            openAuthOfWxCpDk.setSuiteAccessExpireTime(wxAccessToken.getExpiresIn());
            redisUtils.set(RedisKeyConstant.WX_CP_DK_SUITE_ACCESS_TOKEN + suiteId, wxAccessToken, EXPIRE_TIME);
            redisUtils.set(RedisKeyConstant.WX_CP_DK_EXPIRE_IN + suiteId, System.currentTimeMillis() + wxAccessToken.getExpiresIn() * 1000);
        }

        openAuthOfWxCpDk.setPreAuthCode(authCode);
        WxCpTpPermanentCodeInfo wxCpTpPermanentCodeInfo = wxCpTpService.getPermanentCodeInfo(authCode);
        LogUtils.info("========wxCpTpPermanentCodeInfo：{}========", JsonUtils.toJsonStr(wxCpTpPermanentCodeInfo));
        String permanentCode  = wxCpTpPermanentCodeInfo.getPermanentCode();
        String state = wxCpTpPermanentCodeInfo.getState();
        redisUtils.set(RedisKeyConstant.WX_CP_DK_PERMANENT_CODE + suiteId, permanentCode, EXPIRE_TIME);
        openAuthOfWxCpDk.setPermanentCode(permanentCode);
        WxCpTpPermanentCodeInfo.AuthCorpInfo rtnAuthCorpInfo = wxCpTpPermanentCodeInfo.getAuthCorpInfo();

        if(rtnAuthCorpInfo != null) {
            String authCorpId = rtnAuthCorpInfo.getCorpId();
            OpenAuthOfWxCpTpAuthCorpInfo authCorpInfo = BeanUtil.convertBean(rtnAuthCorpInfo, OpenAuthOfWxCpTpAuthCorpInfo.class);
            authCorpInfo.setCorpid(authCorpId);
            param.setAppId(authCorpId);
            if(StringUtils.isNotEmpty(rtnAuthCorpInfo.getCorpRoundLogoUrl())) {
                try {
                    String fileName = (String.valueOf(System.currentTimeMillis())).concat("_".concat(rtnAuthCorpInfo.getCorpId()).concat(".png"));
                    String fileTag = ossPolicyDto.getDir() + fileName;
                    MultipartFile multipartFile = FileUtils.getMultipartFile(rtnAuthCorpInfo.getCorpRoundLogoUrl(), fileName, fileTag);
                    ResponseResult<String> responseResult = openFileFeignClient.uploadFile(multipartFile);
                    String fileUploadPath = responseResult.getData();
                    authCorpInfo.setCorpRoundLogoUrl(UrlUtils.removeUrlDomainName(fileUploadPath));
                } catch (Exception ex) {
                    authCorpInfo.setCorpRoundLogoUrl("");
                }
            }
            if(StringUtils.isNotEmpty(rtnAuthCorpInfo.getCorpSquareLogoUrl())) {
                try {
                    String fileName = (String.valueOf(System.currentTimeMillis())).concat("_".concat(rtnAuthCorpInfo.getCorpId()).concat("_squareLogo.png"));
                    String fileTag = ossPolicyDto.getDir() + fileName;
                    MultipartFile multipartFile = FileUtils.getMultipartFile(rtnAuthCorpInfo.getCorpSquareLogoUrl(), fileName, fileTag);
                    ResponseResult<String> responseResult = openFileFeignClient.uploadFile(multipartFile);
                    String fileUploadPath = responseResult.getData();
                    authCorpInfo.setCorpSquareLogoUrl(UrlUtils.removeUrlDomainName(fileUploadPath));
                } catch (Exception ex) {
                    authCorpInfo.setCorpSquareLogoUrl("");
                }
            }

            if(StringUtils.isNotEmpty(rtnAuthCorpInfo.getCorpWxQrcode())) {
                try {
                    String fileName = (String.valueOf(System.currentTimeMillis())).concat("_".concat(rtnAuthCorpInfo.getCorpId()).concat("_qrcode.png"));
                    String fileTag = ossPolicyDto.getDir() + fileName;
                    MultipartFile multipartFile = FileUtils.getMultipartFile(rtnAuthCorpInfo.getCorpWxQrcode(), fileName, fileTag);
                    ResponseResult<String> responseResult = openFileFeignClient.uploadFile(multipartFile);
                    String fileUploadPath = responseResult.getData();
                    authCorpInfo.setCorpWxqrcode(UrlUtils.removeUrlDomainName(fileUploadPath));
                } catch (Exception ex) {
                    authCorpInfo.setCorpWxqrcode("");
                }
            }
            openAuthOfWxCpDk.setAuthCorpInfo(authCorpInfo);
            WxCpProviderToken wxCpProviderToken = wxCpTpService.getWxCpProviderTokenEntity(true);

            if(wxCpProviderToken != null ){
                String providerAccessToken = wxCpProviderToken.getProviderAccessToken();
                if(StringUtils.isNotEmpty(providerAccessToken)){
                    openAuthOfWxCpDk.setProviderAccessToken(providerAccessToken);
                    openAuthOfWxCpDk.setProviderAccessExpirein(System.currentTimeMillis() + wxCpProviderToken.getExpiresIn() * 1000);
                    openAuthOfWxCpDk.setProviderAccessExpireTime(wxCpProviderToken.getExpiresIn());
                    redisUtils.set(RedisKeyConstant.WX_CP_DK_PROVIDER_ACCESS_TOKEN.concat(suiteId).concat(":").concat(authCorpId), wxCpProviderToken, EXPIRE_TIME);
                }
            }
        }
        WxCpTpPermanentCodeInfo.AuthInfo auThInfo = wxCpTpPermanentCodeInfo.getAuthInfo();
        if(auThInfo != null) {
            List<OpenAuthOfWxCpTpAuthAgentInfo> authAgentInfos = new ArrayList<>();
            List<WxCpTpPermanentCodeInfo.Agent> agentList = auThInfo.getAgents();
            if(Collections3.isNotEmpty(agentList)) {
                agentList.stream().forEach(d -> {
                    Integer agentId = d.getAgentId();
                    OpenAuthOfWxCpTpAuthAgentInfo authAgentInfo = new OpenAuthOfWxCpTpAuthAgentInfo();
                    authAgentInfo.setAgentid(agentId);
                    authAgentInfo.setName(d.getName());
                    authAgentInfo.setAuthMode(d.getAuthMode());
                    authAgentInfo.setAppid(d.getAppid());
                    authAgentInfo.setIsCustomizedApp(d.getIsCustomizedApp());

                    WxCpTpPermanentCodeInfo.Privilege privilege = d.getPrivilege();
                    if (privilege != null) {
                        authAgentInfo.setLevel(privilege.getLevel());
                        List<Integer> allowParties = privilege.getAllowParties();
                        if (Collections3.isNotEmpty(allowParties)) {
                            authAgentInfo.setAllowParty(JsonUtils.toJsonStr(allowParties));
                        }
                        List<Integer> allowTags = privilege.getAllowTags();
                        if (Collections3.isNotEmpty(allowTags)) {
                            authAgentInfo.setAllowTag(JsonUtils.toJsonStr(allowTags));
                        }
                        List<String> allowUsers = privilege.getAllowUsers();
                        if (Collections3.isNotEmpty(allowUsers)) {
                            authAgentInfo.setAllowUser(JsonUtils.toJsonStr(allowUsers));
                        }
                        List<Integer> extraParties = privilege.getExtraParties();
                        if (Collections3.isNotEmpty(extraParties)) {
                            authAgentInfo.setExtraParty(JsonUtils.toJsonStr(extraParties));
                        }
                        List<Integer> extraTags = privilege.getExtraTags();
                        if (Collections3.isNotEmpty(extraTags)) {
                            authAgentInfo.setExtraTag(JsonUtils.toJsonStr(extraTags));
                        }
                        List<String> extraUsers = privilege.getExtraUsers();
                        if (Collections3.isNotEmpty(extraUsers)) {
                            authAgentInfo.setExtraUser(JsonUtils.toJsonStr(extraUsers));
                        }
                    }
                    if (StringUtils.isNotEmpty(d.getSquareLogoUrl())) {
                        try {
                            String fileName = (String.valueOf(System.currentTimeMillis())).concat("_".concat(agentId.toString()).concat("_square.png"));
                            String fileTag = ossPolicyDto.getDir() + fileName;
                            MultipartFile multipartFile = FileUtils.getMultipartFile(d.getSquareLogoUrl(), fileName, fileTag);
                            ResponseResult<String> responseResult = openFileFeignClient.uploadFile(multipartFile);
                            String fileUploadPath = responseResult.getData();
                            authAgentInfo.setSquareLogoUrl(UrlUtils.removeUrlDomainName(fileUploadPath));
                        } catch (Exception ex) {
                            authAgentInfo.setSquareLogoUrl("");
                        }
                    }
                    if (StringUtils.isNotEmpty(d.getRoundLogoUrl())) {
                        try {
                            String fileName = (String.valueOf(System.currentTimeMillis())).concat("_".concat(agentId.toString()).concat("_round.png"));
                            String fileTag = ossPolicyDto.getDir() + fileName;
                            MultipartFile multipartFile = FileUtils.getMultipartFile(d.getRoundLogoUrl(), fileName, fileTag);
                            ResponseResult<String> responseResult = openFileFeignClient.uploadFile(multipartFile);
                            String fileUploadPath = responseResult.getData();
                            authAgentInfo.setRoundLogoUrl(UrlUtils.removeUrlDomainName(fileUploadPath));
                        } catch (Exception ex) {
                            authAgentInfo.setRoundLogoUrl("");
                        }
                    }
                    authAgentInfos.add(authAgentInfo);
                });
                openAuthOfWxCpDk.setAuthAgentInfos(authAgentInfos);
            }
        }
        openAuthOfExtend.setOpenAuthOfWxCpDk(openAuthOfWxCpDk);
        param.setOpenAuthOfExtend(openAuthOfExtend);
        LogUtils.info("========param：{}========", JsonUtils.toJsonStr(param));
        globalOpenAuthFeignClient.modifyAuth(param);
    }

    @Override
    public Object msgWxCpDkEvent(HttpServletRequest request, HttpServletResponse response, String signature, String timestamp, String nonce, String echostr) {
       try {
           WxCpTpService wxCpTpService = openServiceImpl.getDefaultWxCpDkService();
           if (wxCpTpService == null) {
               throw new BusinessException("获取企微服务失败!");
           }
           WxCpTpConfigStorage wxCpTpConfigStorage = wxCpTpService.getWxCpTpConfigStorage();
           WxCpTpCryptUtil cryptUtil = new WxCpTpCryptUtil(wxCpTpConfigStorage);

           String inMessage = cryptUtil.decryptXml(signature, timestamp, nonce, IOUtils.toString(request.getInputStream(), StandardCharsets.UTF_8));
           if(inMessage == null) return "success";

           LogUtils.info("msgCpDkEvent:消息解密后内容为：\n{} ", JsonUtils.toJsonStr(inMessage));

           WxCpTpXmlMessage wxCpTpXmlMessage = WxCpTpXmlMessage.fromXml(inMessage);
           String out = "success";

           return out;
       }catch(Exception ex){
           return "";
       }

    }

    private WxCpMessageRouter getWxCpMessageRouterByAppid(String agentId) {
        WxCpMessageRouter wxCpMessageRouter = wxCpMessageRouterMap.get(agentId);
//        if (wxCpMessageRouter == null) {
//            synchronized (wxCpMessageRouterMap) {
//                wxCpMessageRouter = wxCpMessageRouterMap.get(agentId);
//                if (wxCpMessageRouter == null) {
//                    wxCpMessageRouter = new WxCpMessageRouter(openServiceImpl.getWxCpService());
//                    wxCpMessageRouterMap.put(agentId, wxCpMessageRouter);
//                    addTxtMsgRouter(agentId, wxCpMessageRouter);
//                    addEventRouter(agentId, wxCpMessageRouter);
//                }
//            }
//        }
        return wxCpMessageRouter;
    }

    private void addEventRouter(final String appId, WxCpMessageRouter wxCpMessageRouter) {
        WxCpMessageHandler handler = new WxCpMessageHandler() {
            public WxCpXmlOutMessage handle(WxCpXmlMessage wxMessage, Map<String, Object> context, WxCpService wxCpService, WxSessionManager sessionManager) throws WxErrorException {
                WxCpXmlOutTextMessage m = null;
                // 订阅事件
                if (wxMessage.getEvent().equals(WxConsts.EventType.SUBSCRIBE)) {
                    if (wxMessage.getEventKey().startsWith("qrscene_") && wxMessage.getTicket() != null) {
                        String msg = wxMessage.getContent().replace("QUERY_AUTH_CODE:", "") + "_from_api";
                        WxCpMessage kefuMessage = WxCpMessage.TEXT().content(msg).toUser(wxMessage.getFromUserName()).build();
                        wxCpService.getMessageService().send(kefuMessage);
                    }
                } else if (wxMessage.getEvent().equals(WxConsts.EventType.SCAN)) {
                    // 扫码 用户已关注时的事件推送
                    if (wxMessage.getEventKey() != null || wxMessage.getTicket() != null) {
                        String msg = wxMessage.getContent().replace("QUERY_AUTH_CODE:", "") + "_from_api";
                        WxCpMessage kefuMessage = WxCpMessage.TEXT().content(msg).toUser(wxMessage.getFromUserName()).build();
                        wxCpService.getMessageService().send(kefuMessage);
                    }
                } else if (wxMessage.getEvent().equals(WxConsts.EventType.CLICK)) {// 自定义菜单点击事件
                    if (wxMessage.getEventKey() != null && !wxMessage.getEventKey().equals("")) {
                        System.out.println("事件KEY值，与自定义菜单接口中KEY值对应");
                    }
                } else if (wxMessage.getEvent().equals(WxConsts.EventType.VIEW)) {
                    System.out.println("点击菜单跳转链接时的事件推送");
                }
                return m;
            }
        };
        wxCpMessageRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT).handler(handler).end();
    }

    private void addTxtMsgRouter(final String appId, WxCpMessageRouter wxCpMessageRouter) {
        WxCpMessageHandler handler = new WxCpMessageHandler() {
            public WxCpXmlOutMessage handle(WxCpXmlMessage wxMessage, Map<String, Object> context,
                                            WxCpService wxCpService, WxSessionManager sessionManager) throws WxErrorException {
                WxCpXmlOutTextMessage m = null;
                String keys = wxMessage.getContent();
                if (keys.startsWith("xxxxx")&& wxMessage.getFromUserName().equals("DSFGDFNMHJJHJ")) {
                    String msg = wxMessage.getContent().replace("QUERY_AUTH_CODE:", "") + "_from_api";
                    WxCpMessage wxCpMessage = WxCpMessage.TEXT().content(msg).toUser(wxMessage.getFromUserName()).build();
                    wxCpService.getMessageService().send(wxCpMessage);
                }
                return m;
            }
        };
        wxCpMessageRouter.rule().async(false).msgType(WxConsts.XmlMsgType.TEXT).handler(handler).end();
    }

    /**
     * 授权注册页面扫码授权   显示二维码
     *
     * @param request
     * @return
     * @throws Exception
     * @Author ibeeking
     */
    @Override
    public UrlVO getWxCpDkPreAuthUrl(HttpServletRequest request, HttpServletResponse response) throws Exception {
        String qrCodeFileUrl = "";
        String tenantId = UserUtils.getTenantId();
        String qrCodeKey = RedisKeyConstant.WX_CP_DK_AUTH_QRCODE.concat(tenantId);
        Boolean needRestQrCode = false;
        Object wxCpDkQrCodeDTOObj = redisUtils.get(qrCodeKey);
        if(ObjectUtils.isNotEmpty(wxCpDkQrCodeDTOObj)){
            WxCpDkQrCodeDTO qrCodeDTO = (WxCpDkQrCodeDTO)wxCpDkQrCodeDTOObj;
            qrCodeFileUrl = qrCodeDTO.getQrCodeUrl();
            Long expiredIn = qrCodeDTO.getQrCodeExpiresIn();
            Long currentTime = System.currentTimeMillis();
            if((expiredIn - currentTime) <=0){
                needRestQrCode = true;
            }
        }else {
            needRestQrCode = true;
        }
        if(needRestQrCode){
            OpenConfigDTO wxOpenConfigDTO = queryWxOpenConfigByType(OpenApiConfigEnum.OPEN_CONFIG_TYPE_WECHAT_CP.getCode(), WxCpAppTypeEnum.WECHAT_CP_APP_TYPE_DK.getCode());
            DataUtils.trueThrowException(wxOpenConfigDTO == null, "系统异常:微信第三放平台appId为空!");
            String corpAppId = wxOpenConfigDTO.getOpenAppId();
            String suiteId = wxOpenConfigDTO.getComponentAppId();

            String wxOpenCpDkAuthRedirectUrl = openAuthCallBackConfig.getWxOpenCpDkAuthRedirectUrl();

            DataUtils.trueThrowException(StringUtils.isBlank(wxOpenCpDkAuthRedirectUrl), "微信第三方授权后的跳转页面尚未配置!");

            WxCpTpService wxCpDkService = openServiceImpl.getDefaultWxCpDkService();
            if (null == wxCpDkService) throw new BusinessException("企业微信服务初始化还未完成，请稍候再试");
            WxCpTpConfigStorage configStorage = wxCpDkService.getWxCpTpConfigStorage();
           // wxCpTpService.setWxCpTpConfigStorage(configStorage);

            String suiteTicket = configStorage.getSuiteTicket();
            if (StringUtils.isEmpty(suiteTicket)) {
                Object suiteTicketObj = redisUtils.get(RedisKeyConstant.WX_CP_DK_SUITE_TICKET + suiteId);
                if (ObjectUtils.isNotEmpty(suiteTicketObj)) {
                    configStorage.updateSuiteTicket(suiteTicketObj.toString(), 1200);
                }
            }
            String suiteAccessToken = configStorage.getSuiteAccessToken();
            if (StringUtils.isEmpty(suiteAccessToken)) {
                WxAccessToken wxAccessToken = wxCpDkService.getSuiteAccessTokenEntity(true);
                if (ObjectUtils.isNotEmpty(wxAccessToken)) {
                    configStorage.updateSuiteAccessToken(wxAccessToken.getAccessToken(), wxAccessToken.getExpiresIn());
                    redisUtils.set(RedisKeyConstant.WX_CP_DK_SUITE_ACCESS_TOKEN + suiteId, wxAccessToken, EXPIRE_TIME.intValue());
                    redisUtils.set(RedisKeyConstant.WX_CP_DK_EXPIRE_IN + suiteId, System.currentTimeMillis() + wxAccessToken.getExpiresIn() * 1000);

                }
            }

            wxCpDkService.setWxCpTpConfigStorage(configStorage);
            List<String> templateList = new ArrayList<>();
            templateList.add(suiteId);
            WxTpCustomizedAuthUrl wxTpCustomizedAuthUrl = wxCpDkService.getCustomizedAuthUrl(tenantId, templateList);
            String url = wxTpCustomizedAuthUrl.getQrCodeURL();
            Integer expiresTimes = wxTpCustomizedAuthUrl.getExpiresIn();
            Long expiresIn = System.currentTimeMillis() + expiresTimes * 900;
            OssPolicyDto ossPolicyDto = getOssFilePolicy();
            String qrCodeFilename = String.valueOf("qrcode_").concat(String.valueOf(System.currentTimeMillis())).concat(".png");
            String fileTag = ossPolicyDto.getDir() + qrCodeFilename;
            MultipartFile multipartFile = generateQrcode(url, qrCodeFilename, fileTag);
            ResponseResult<String> responseResult = openFileFeignClient.uploadFile(multipartFile);
            qrCodeFileUrl = responseResult.getData();
            WxCpDkQrCodeDTO qrCodeDTO = new WxCpDkQrCodeDTO();
            qrCodeDTO.setQrCodeUrl(qrCodeFileUrl);
            qrCodeDTO.setQrCodeExpiresIn(expiresIn);
            redisUtils.set(qrCodeKey, qrCodeDTO, expiresTimes);
        }
        return new UrlVO().setUrl(qrCodeFileUrl);
    }

    private WxCpXmlOutMessage route(Integer agentId, WxCpXmlMessage message) {
//        try {
//            return WxCpConfiguration.getRouters().get(agentId).route(message);
//        } catch (Exception e) {
//            LogUtils.error(e.getMessage(), e);
//        }

        return null;
    }

    @Override
    public OpenAuthVO queryWxCpDkOpenAuthInfo()  {
        Long tenantId = UserUtils.getTenantID();
        if(tenantId == null){
            DataUtils.trueThrowException(true, "获取租户tenantId失败:" + tenantId);
        }

        OpenAuthDTO wxOpenAuthDTO = queryWxOpenAuthByType(tenantId, WxCpServiceTypeConstant.CP_TYPE_DK);
        if (null != wxOpenAuthDTO) {
            OpenAuthOfExtend openAuthOfExtend = wxOpenAuthDTO.getOpenAuthOfExtend();
            if(openAuthOfExtend!=null) {
                OpenAuthOfWxCpDk openAuthOfWxCpDk = openAuthOfExtend.getOpenAuthOfWxCpDk();
                if(openAuthOfWxCpDk!=null) {
                    OssPolicyDto ossPolicyDto = getOssPolicy();
                    if (null != ossPolicyDto) {
                        OpenAuthOfWxCpTpAuthCorpInfo authCorpInfo = openAuthOfWxCpDk.getAuthCorpInfo();
                        String dnsHost = ossPolicyDto.getHost();
                        if (StringUtils.isNotEmpty(authCorpInfo.getCorpSquareLogoUrl())) {
                            authCorpInfo.setCorpSquareLogoUrl(dnsHost + "/" + authCorpInfo.getCorpSquareLogoUrl());
                        }
                        if (StringUtils.isNotEmpty(authCorpInfo.getCorpWxqrcode())) {
                            authCorpInfo.setCorpWxqrcode(dnsHost + "/" + authCorpInfo.getCorpWxqrcode());
                        }
                    }
                    wxOpenAuthDTO.setHasOpenAuth(openAuthOfWxCpDk.getProviderAccessToken()!=null);
                }
            }
            return BeanUtil.convertBean(wxOpenAuthDTO, OpenAuthVO.class);
        } else {
            OpenAuthVO openAuthVO = new OpenAuthVO();
            openAuthVO.setTenantId(tenantId);
            OpenAuthOfExtend openAuthOfExtend = new OpenAuthOfExtend();
            OpenAuthOfWxCpDk openAuthOfWxCpDk = new OpenAuthOfWxCpDk();
            openAuthOfWxCpDk.setAuthCorpInfo(new OpenAuthOfWxCpTpAuthCorpInfo());
            openAuthOfWxCpDk.setAuthAgentInfos(new ArrayList<>());
            openAuthOfExtend.setOpenAuthOfWxCpDk(openAuthOfWxCpDk);
            openAuthVO.setOpenAuthOfExtend(openAuthOfExtend);
            openAuthVO.setHasOpenAuth(openAuthOfWxCpDk.getProviderAccessToken()!=null);
            return openAuthVO;
        }
    }

    private void checkAndUpdateSuiteToken(WxCpTpService wxCpTpService, String suiteId, String signature, String timestamp, String nonce){
        WxCpTpConfigStorage wxCpTpConfigStorage = wxCpTpService.getWxCpTpConfigStorage();
        Object objSuiteAccessTokenEntity = redisUtils.get(RedisKeyConstant.WX_CP_DK_SUITE_ACCESS_TOKEN + suiteId);
        if(ObjectUtils.isNotEmpty(objSuiteAccessTokenEntity)) {
            Long oldExpiresIn = redisUtils.getLong(RedisKeyConstant.WX_CP_DK_EXPIRE_IN + suiteId);
            if(oldExpiresIn == null) oldExpiresIn =  System.currentTimeMillis();
            if ((oldExpiresIn - System.currentTimeMillis()) <= 600*1000) {
                try {
                    WxAccessToken newSuiteAccessTokenEntity = wxCpTpService.getSuiteAccessTokenEntity(true);
                    if (newSuiteAccessTokenEntity != null) {
                        wxCpTpConfigStorage.updateSuiteAccessToken(newSuiteAccessTokenEntity);
                        redisUtils.set(RedisKeyConstant.WX_CP_DK_SUITE_ACCESS_TOKEN + suiteId, newSuiteAccessTokenEntity, EXPIRE_TIME.intValue());
                        redisUtils.set(RedisKeyConstant.WX_CP_DK_EXPIRE_IN + suiteId, System.currentTimeMillis() + newSuiteAccessTokenEntity.getExpiresIn() * 1000);
                    }
                } catch (WxErrorException ex) {
                    throw new BusinessException("获取suiteAccessToken 出错");
                }
            }
        }else{
            try {
                WxAccessToken newSuiteAccessTokenEntity = wxCpTpService.getSuiteAccessTokenEntity(true);
                if (newSuiteAccessTokenEntity != null) {
                    wxCpTpConfigStorage.updateSuiteAccessToken(newSuiteAccessTokenEntity);
                    redisUtils.set(RedisKeyConstant.WX_CP_DK_SUITE_ACCESS_TOKEN + suiteId, newSuiteAccessTokenEntity, EXPIRE_TIME.intValue());
                    redisUtils.set(RedisKeyConstant.WX_CP_DK_EXPIRE_IN + suiteId, System.currentTimeMillis() + newSuiteAccessTokenEntity.getExpiresIn() * 1000);
                }
            } catch (WxErrorException ex) {
                throw new BusinessException("获取suiteAccessToken 出错");
            }
        }
    }
    /**
     * 跟新授权Token
     *
     * @param componentAppId
     * @param wxCpDkService
     */
    private void checkAndUpdateWxCpDkAuthorizeAccessToken(WxCpTpService wxCpDkService, String componentAppId, String timestamp, String nonce, String signature) throws Exception{
        List<OpenAuthDTO> wxOpenAuthDTOS = queryWxOpenAuthListByComponentID(componentAppId);
        if(Collections3.isNotEmpty(wxOpenAuthDTOS)) {
            wxOpenAuthDTOS.stream().forEach(wxOpenAuthDTO -> {
                try {
                    checkAndUpdateWxCpDkGlobalOpenAuthParam(wxCpDkService, wxOpenAuthDTO, timestamp, nonce, signature);
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            });
        }
    }

    /**
     * 跟新授权Token
     *
     * @param wxCpDkService
     */
    private void checkAndUpdateWxCpDkGlobalOpenAuthParam(WxCpTpService wxCpDkService, OpenAuthDTO wxOpenAuthDTO, String timestamp, String nonce, String signature)  throws Exception{
            //更新global OpenAuth
            if (null != wxOpenAuthDTO) {
                OpenAuthOfExtend openAuthOfExtend = wxOpenAuthDTO.getOpenAuthOfExtend();
                if(openAuthOfExtend == null) throw new BusinessException("读取三方应用配置参数openAuthOfExtend出错！");
                OpenAuthOfWxCpDk openAuthOfWxCpDk = openAuthOfExtend.getOpenAuthOfWxCpDk();
                if(openAuthOfWxCpDk == null) throw new BusinessException("读取三方应用配置参数openAuthOfWxCpDk出错！");
                openAuthOfWxCpDk.setSignature(signature);
                openAuthOfWxCpDk.setTimestamp(timestamp);
                openAuthOfWxCpDk.setNonceStr(nonce);
                Long tenantId = wxOpenAuthDTO.getTenantId();
                String suiteId = wxOpenAuthDTO.getComponentAppId();
                String openAppId = wxOpenAuthDTO.getOpenAppId();
                String permanentCode = openAuthOfWxCpDk.getPermanentCode();
                String appId = wxOpenAuthDTO.getAppId();

                WxCpTpConfigStorage wxCpDkConfigStorage = wxCpDkService.getWxCpTpConfigStorage();
                String suiteAccessToken = wxCpDkConfigStorage.getSuiteAccessToken();
                String suiteTicket = wxCpDkConfigStorage.getSuiteTicket();
                String providerAccessToken = wxCpDkConfigStorage.getProviderToken();

                Boolean needUpdateAccessTokenInDb = false;
                Object oldCorpAccessTokenObj = redisUtils.get(RedisKeyConstant.WX_CP_DK_PROVIDER_ACCESS_TOKEN.concat(suiteId).concat(":").concat(appId));
                if(ObjectUtils.isEmpty(oldCorpAccessTokenObj) ) {
                    WxCpProviderToken wxCpProviderToken = wxCpDkService.getWxCpProviderTokenEntity(true);
                    if (wxCpProviderToken != null) {
                        providerAccessToken = wxCpProviderToken.getProviderAccessToken();
                        if (StringUtils.isNotEmpty(providerAccessToken)) {
                            wxCpDkConfigStorage.updateProviderToken(providerAccessToken, wxCpProviderToken.getExpiresIn());
                            redisUtils.set(RedisKeyConstant.WX_CP_DK_PROVIDER_ACCESS_TOKEN.concat(suiteId).concat(":").concat(appId), wxCpProviderToken, EXPIRE_TIME);
                            String newJsapiTicketOfSuite = wxCpDkService.getSuiteJsApiTicket(appId, true);
                            if(StringUtils.isNotEmpty(newJsapiTicketOfSuite)){
                                wxCpDkConfigStorage.updateAuthSuiteJsApiTicket(appId, newJsapiTicketOfSuite, wxCpProviderToken.getExpiresIn());
                            }
                            String newJsapiTicketOfApp = wxCpDkService.getAuthCorpJsApiTicket(appId, true);
                            if(StringUtils.isNotEmpty(newJsapiTicketOfApp)){
                                wxCpDkConfigStorage.updateAuthCorpJsApiTicket(appId, newJsapiTicketOfApp, wxCpProviderToken.getExpiresIn());
                            }
                            needUpdateAccessTokenInDb = true;
                        }
                    }
                }else{
                    Long providerAccessExpiredIn = openAuthOfWxCpDk.getProviderAccessExpirein();
                    if (providerAccessExpiredIn == null) providerAccessExpiredIn = System.currentTimeMillis();
                    if ((providerAccessExpiredIn - System.currentTimeMillis()) <= 600 * 1000) {
                        WxCpProviderToken wxCpProviderToken = wxCpDkService.getWxCpProviderTokenEntity(true);
                        if (wxCpProviderToken != null) {
                            providerAccessToken = wxCpProviderToken.getProviderAccessToken();
                            wxCpDkConfigStorage.updateProviderToken(providerAccessToken, wxCpProviderToken.getExpiresIn());
                            redisUtils.set(RedisKeyConstant.WX_CP_DK_PROVIDER_ACCESS_TOKEN.concat(suiteId).concat(":").concat(appId), wxCpProviderToken, EXPIRE_TIME);
                            String newJsapiTicketOfSuite = wxCpDkService.getSuiteJsApiTicket(appId, true);
                            if(StringUtils.isNotEmpty(newJsapiTicketOfSuite)){
                                wxCpDkConfigStorage.updateAuthSuiteJsApiTicket(appId, newJsapiTicketOfSuite, wxCpProviderToken.getExpiresIn());
                            }
                            String newJsapiTicketOfApp = wxCpDkService.getAuthCorpJsApiTicket(appId, true);
                            if(StringUtils.isNotEmpty(newJsapiTicketOfApp)){
                                wxCpDkConfigStorage.updateAuthCorpJsApiTicket(appId, newJsapiTicketOfApp, wxCpProviderToken.getExpiresIn());
                            }
                            needUpdateAccessTokenInDb = true;
                        }
                    }
                }
               // wxCpDkService.setWxCpTpConfigStorage(wxCpDkConfigStorage);
                LogUtils.info("=======WxCpDkConfigStorage:{}=========",JsonUtils.toJsonStr(wxCpDkConfigStorage));
                if (needUpdateAccessTokenInDb) {
                    OpenAuthParam openAuthParam = BeanUtil.convertBean(wxOpenAuthDTO, OpenAuthParam.class);
                    openAuthParam.setConfigType(OpenApiConfigEnum.OPEN_CONFIG_TYPE_WECHAT_CP.getCode());
                    openAuthParam.setConfigSubType(WxCpAppTypeEnum.WECHAT_CP_APP_TYPE_DK.getCode());

                    if (StringUtils.isNotEmpty(suiteTicket)) {
                        openAuthOfWxCpDk.setSuiteTicket(suiteTicket);
                    }

                    if (StringUtils.isNotEmpty(suiteAccessToken)) {
                        WxAccessToken suiteAccessTokenEntity = wxCpDkConfigStorage.getSuiteAccessTokenEntity();
                        openAuthOfWxCpDk.setSuiteAccessToken(suiteAccessTokenEntity.getAccessToken());
                        openAuthOfWxCpDk.setSuiteAccessExpireTime(suiteAccessTokenEntity.getExpiresIn());
                        openAuthOfWxCpDk.setSuiteAccessExpirein(System.currentTimeMillis() + suiteAccessTokenEntity.getExpiresIn() * 1000);
                    }

                    if (StringUtils.isNotEmpty(providerAccessToken)) {
                        WxCpProviderToken providerAccessTokenEntity = wxCpDkConfigStorage.getProviderTokenEntity();
                        openAuthOfWxCpDk.setProviderAccessToken(providerAccessTokenEntity.getProviderAccessToken());
                        openAuthOfWxCpDk.setProviderAccessExpireTime(providerAccessTokenEntity.getExpiresIn());
                        openAuthOfWxCpDk.setProviderAccessExpirein(System.currentTimeMillis() + providerAccessTokenEntity.getExpiresIn() * 1000);
                    }
                    String suiteJsapiTicket = wxCpDkConfigStorage.getAuthSuiteJsApiTicket(appId);
                    if (StringUtils.isNotEmpty(suiteJsapiTicket)) {
                        openAuthOfWxCpDk.setJsapiTicketOfSuite(suiteJsapiTicket);
                        openAuthOfWxCpDk.setJsapiTicketOfSuiteExpireTime(EXPIRE_TIME);
                        openAuthOfWxCpDk.setJsapiTicketOfSuiteExpirein(System.currentTimeMillis() + EXPIRE_TIME);
                    }
                    String appJsapiTicket = wxCpDkConfigStorage.getAuthCorpJsApiTicket(appId);
                    if (StringUtils.isNotEmpty(appJsapiTicket)) {
                        openAuthOfWxCpDk.setJsapiTicketOfApp(appJsapiTicket);
                        openAuthOfWxCpDk.setJsapiTicketOfAppExpireTime(EXPIRE_TIME);
                        openAuthOfWxCpDk.setJsapiTicketOfAppExpirein(System.currentTimeMillis() + EXPIRE_TIME);
                    }
                    openAuthOfExtend.setOpenAuthOfWxCpDk(openAuthOfWxCpDk);
                    openAuthParam.setOpenAuthOfExtend(openAuthOfExtend);
                    LogUtils.info("\n update WxCpDk openAuthParam：\n{} ", JsonUtils.toJsonStr(openAuthParam));
                    globalOpenAuthFeignClient.modifyAuth(openAuthParam);
                }
            }
    }

    private OssPolicyDto getOssPolicy() {
        ResponseResult<OssPolicyDto> ossPolicyResult = openFileFeignClient.policy();
        DataUtils.trueThrowException(!ResponseCodeEnum.SUCCESS.getCode().equals(ossPolicyResult.getCode()), ossPolicyResult.getMsg());
        return ossPolicyResult.getData();
    }
    /**
     * @return
     * @Author ibeeking
     * 返回公众号授权信息
     */
    private OpenAuthDTO queryWxOpenAuthByType(Long tenantId, Integer appType) {
        OpenAuthQuery query = new OpenAuthQuery();
        query.setTenantId(tenantId);
        query.setAppType(appType);
        ResponseResult<OpenAuthDTO> responseResult = globalOpenFeignClient.queryOpenAuthOne(query);
        return responseResult.getData();
    }

    private List<OpenAuthDTO> queryWxOpenAuthListByComponentID(String componentAppId) {
        OpenAuthQuery query = new OpenAuthQuery();
        query.setComponentAppId(componentAppId);
        ResponseResult<List<OpenAuthDTO>> responseResult = globalOpenFeignClient.queryOpenAuthList(query);
        return responseResult.getData();
    }

    private OpenConfigDTO queryWxOpenConfigByType(Integer type,Integer subType) {
        OpenConfigQuery query = new OpenConfigQuery();
        query.setType(type);
        query.setSubType(subType);
        ResponseResult<OpenConfigDTO> responseResult = globalOpenFeignClient.queryOpenConfigOne(query);
        return responseResult.getData();
    }

    private WxAccessToken getContactAccessToken(WxCpTpService wxCpTpService, String corpId, String corpSecret) {
        try {
            WxCpTpServiceImpl wxCpTpServiceImpl = new WxCpTpServiceImpl();
            WxCpTpDefaultConfigImpl configStorage = new WxCpTpDefaultConfigImpl();
            wxCpTpServiceImpl.setWxCpTpConfigStorage(configStorage);

            String url = String.format(configStorage.getApiUrl(WxCpApiPathConsts.GET_TOKEN), corpId, corpSecret);
            try {
                HttpGet httpGet = new HttpGet(url);
                String resultContent;
                try (CloseableHttpClient httpClient = wxCpTpServiceImpl.getRequestHttpClient();
                    CloseableHttpResponse response = httpClient.execute(httpGet)) {
                    resultContent = new BasicResponseHandler().handleResponse(response);
                } finally {
                    httpGet.releaseConnection();
                }
                WxError error = WxError.fromJson(resultContent, WxType.CP);
                if (error.getErrorCode() != 0) {
                    throw new WxErrorException(error);
                }

                WxAccessToken accessToken = WxAccessToken.fromJson(resultContent);
                return accessToken;
            } catch (IOException e) {
                throw new WxRuntimeException(e);
            }
        }catch(WxErrorException ex){
            return null;
        }
    }

    private OssPolicyDto getOssFilePolicy(){
        ResponseResult<OssPolicyDto> responseResult = openFileFeignClient.policy();
        return responseResult.getData();
    }

    private MultipartFile generateQrcode(String content , String fileName, String fileTag){
        OutputStream osStream = null;
        try {
            FileItemFactory factory = new DiskFileItemFactory(16, null);
            FileItem item = factory.createItem(fileTag, ContentType.APPLICATION_OCTET_STREAM.toString(), false, fileName);
            osStream = item.getOutputStream();
            QrcodeConfig config = new QrcodeConfig(400, 400)
                    .setBorderSize(0) // 外层虚线Border
                    .setPadding(10) // 二维码离虚线的填充空白
                    .setMasterColor("#000000") // 二维码颜色
                    .setLogoBorderColor("#DB7093") // LOGO边框颜色
                    .setLogoShape(Codectx.LogoShape.RECTANGLE) // 圆形logo
                    .setCodeEyesPointColor("#1E90FF") // 三个对焦方框为眼眶样式，中间填充点的颜色
                    .setCodeEyesFormat(QreyesFormat.DR2_BORDER_R_POINT);// 三个对焦方框为眼眶样式，中间填充点的样式
            SimpleQrcodeGenerator qrcodeGenerator = new SimpleQrcodeGenerator(config);
            qrcodeGenerator.generate(content);
            qrcodeGenerator.toStream(osStream);
            return new CommonsMultipartFile(item);
        }catch(IOException  ex1){
            ex1.printStackTrace();
        }finally {
            try {
                osStream.close();
            }catch(Exception ex){}
        }
        return null;
    }
}
